package com.gitee.wsl.net.client

import com.gitee.wsl.transform.validator.ValidatorsRegistry
import com.gitee.wsl.transform.validator.ValidatorsRegistryScope
import io.ktor.client.HttpClientConfig
import io.ktor.client.call.body
import io.ktor.client.engine.ProxyBuilder
import io.ktor.client.engine.http
import io.ktor.client.plugins.HttpCallValidator
import io.ktor.client.plugins.HttpRequestRetry
import io.ktor.client.plugins.HttpRequestRetryConfig
import io.ktor.client.plugins.HttpTimeout
import io.ktor.client.plugins.HttpTimeoutConfig
import io.ktor.client.plugins.auth.Auth
import io.ktor.client.plugins.auth.AuthConfig
import io.ktor.client.plugins.cache.HttpCache
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.cookies.HttpCookies
import io.ktor.client.plugins.logging.LogLevel
import io.ktor.client.plugins.logging.Logging
import io.ktor.client.plugins.logging.LoggingConfig
import io.ktor.client.plugins.sse.SSE
import io.ktor.client.plugins.sse.SSEConfig
import io.ktor.client.plugins.websocket.WebSockets
import io.ktor.client.plugins.websocket.WebSockets.Config
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json
import kotlin.reflect.KClass

fun HttpClientConfig<*>.auth(block: AuthConfig.() -> Unit) {
    install(Auth, block)
}

fun HttpClientConfig<*>.webSockets(pluginConfig: Config.() -> Unit){
    install(WebSockets,pluginConfig)
}

fun HttpClientConfig<*>.json(json: Json = Json.Default){
    install(ContentNegotiation) {
        json(json)
    }
}

fun HttpClientConfig<*>.httpTimeout(pluginConfig: HttpTimeoutConfig.() -> Unit){
    install(HttpTimeout,pluginConfig)
}

fun HttpClientConfig<*>.httpCookies(pluginConfig: HttpCookies.Config.() -> Unit){
    install(HttpCookies,pluginConfig)
}

fun HttpClientConfig<*>.proxy(url:String){
    engine {
        proxy = ProxyBuilder.http(url)
    }
}

fun HttpClientConfig<*>.sockProxy(host:String,port:Int){
    engine {
        proxy = ProxyBuilder.socks(host, port)
    }
}

fun HttpClientConfig<*>.sse(block: SSEConfig.()->Unit){
    install(SSE,block)

}

/*fun HttpClientConfig<*>.callId(
    header:String = HttpHeaders.XRequestId,
    callLogging:String? = null,
    callIdBlock:(callId: String) -> Unit
){
    install(CallId) {
        header(header)
        verify { callId: String ->
           callIdBlock(callId)
        }
    }

    callLogging?.let {
        install(CallLogging) {
            callIdMdc(it)
        }
    }
}*/


fun HttpClientConfig<*>.httpCache(block: HttpCache.Config.()->Unit){
    install(HttpCache,block)
}

fun HttpClientConfig<*>.logging(level: LogLevel = LogLevel.INFO){
    install(Logging){
        this.level=level
    }

}

fun HttpClientConfig<*>.logging(block: LoggingConfig.()->Unit){
    install(Logging,block)
}

fun HttpClientConfig<*>.retry(block:HttpRequestRetryConfig.()->Unit){
    install(HttpRequestRetry,block)
}

fun HttpClientConfig<*>.validate(block: ValidatorsRegistryScope.() -> Unit){
    install(HttpCallValidator){
        val validatorsRegistry = ValidatorsRegistry()
        block(validatorsRegistry)
        validateResponse{response ->
            val body = response.body<Any>()
            validatorsRegistry[body::class]?:return@validateResponse
            validatorsRegistry.validateWithResult(body).onFailure {
                throw ResponseException(response.status.value,it.message?:"")
            }
        }
    }
}


